package master;

import java.awt.*;

import javax.swing.*;


public class ComplexNumber{
	
	protected float re, im;
	
	public float getReal(){return re;}
	public float getImaginary(){return im;}
	
	public ComplexNumber magnitude(){
		return new ComplexNumber((float)Math.hypot(getReal(), getImaginary()),0);
	}
	public float magnitudeFloat(){
		return (float)Math.hypot(getReal(), getImaginary());
	}
	
	public ComplexNumber phase(){
		float r = Math.abs(getReal()),i = Math.abs(getImaginary());
		float phase = (float)(Math.atan(i/r));
		
		if(getReal() < 0)phase = (float)Math.PI - phase;
		if(getImaginary() < 0) phase = (2*(float)Math.PI) -phase;
		
		return new ComplexNumber( phase ,0);
	}
	public ComplexNumber conjugate(){
		return new ComplexNumber(getReal(),-getImaginary());
	}
	public void setMagnitude(float m){
		float mag = this.magnitude().getReal();
		float r = this.getReal();
		float i = this.getImaginary();
		System.out.println(r + "  " + i);
		r = r/mag; r *= m;
		i = i / mag; i *=m;
		
		setReal(r);
		setImaginary(i);
	}
	public static ComplexNumber expi(float magnitude, float theta){
		return new ComplexNumber(
				(float) (magnitude*Math.cos(theta)),
				(float) (magnitude*Math.sin(theta))
				)
				;
	}
	
	public void setReal(float re){
		this.re = re;
	}
	
	public void setImaginary(float im){
		this.im = im;
	}
	
	private ComplexNumber compatibilityCast(ComplexNumber b){
		if ( b instanceof ComplexNumber) return (ComplexNumber)b;
		throw new IllegalArgumentException("Not Compatible!");
	}
	
	public ComplexNumber(){
		this.re = 0.0f;
		this.im = 0.0f;
	}
	
	public ComplexNumber(float re, float im){
		this.re = re;
		this.im = im;
	}
	
	public ComplexNumber add(ComplexNumber b) {
		ComplexNumber op = compatibilityCast(b);
		this.re += op.getReal();
		this.im += op.getImaginary();
		return this;
	}

	public ComplexNumber subtract(ComplexNumber b) {
		ComplexNumber op = compatibilityCast(b);
		this.re -= op.getReal();
		this.im -= op.getImaginary();
		return this;
	}

	public ComplexNumber multiply(ComplexNumber f) {
		ComplexNumber op = compatibilityCast(f);
		float a = this.getReal() ,
			b = this.getImaginary() ,
			c = op.getReal() ,
			d = op.getImaginary();
		this.re = a*c - b*d;
		this.im = a*d +b*c;
		return this;
	}
	
	public ComplexNumber multByNo(float a){
		this.re = this.re * a;
		this.im = this.im * a;
		
		return this;
	}

	public ComplexNumber divide(ComplexNumber f) {
		ComplexNumber op = compatibilityCast(f.createNewInstance());
		return this.multiply(op.invert());
	}
	
	public ComplexNumber invert() {
		float a = this.getReal() , b = this.getImaginary();
		this.re = a / (a*a + b*b);
		this.im = - b /(a*a + b*b);
		return this;
	}
	
	public ComplexNumber negate() {
		re = -getReal();
		im = -getImaginary();
		return this;
	}
	
	public ComplexNumber createNewInstance() {
		return new ComplexNumber(getReal(),getImaginary());
	}

	public ComplexNumber setZero() {
		setReal(0);
		setImaginary(0);
		return this;
	}
	
	public boolean isZero() {
		return (getReal() == 0 && getImaginary() == 0);
	}
	
	public ComplexNumber setUnity() {
		setReal(1f);
		setImaginary(0);
		return this;
	}
	
	public boolean isUnity() {
		return (getReal() == 1 && getImaginary() == 0);
	}

	
	public boolean equals(ComplexNumber b) {
		ComplexNumber op = compatibilityCast(b);
		return (re == op.getReal() && im == op.getImaginary());
	}

	public String toString(){
		String val = "";
		if(getReal() != 0)val += getReal();
		if(getImaginary() != 0){
			val += " ";
			if(getImaginary() > 0 && getReal()!=0) val += "+";
			val+=getImaginary();
			val+="i";
		}
		return val;
	}
	
	public void draw(Graphics g, int x, int y, float multiplier){
		int drawX =  x + (int)(getReal()*multiplier);
		int drawY = y - (int)(getImaginary()*multiplier);
		g.drawLine(x, y, drawX, drawY);
		g.drawOval(drawX-5, drawY-5, 10, 10);
		//draw line
	}
	
	public static void display(String title,boolean horizontal , boolean editable, ComplexNumber ... numbers){
		JFrame myFrame = new JFrame();
		myFrame.setTitle(title);
		int defaultDimension = 200;
		if(horizontal){
			myFrame.setLayout(new GridLayout(1,numbers.length));
			myFrame.setSize(defaultDimension*numbers.length,defaultDimension);
		}
		else{
			myFrame.setLayout(new GridLayout(numbers.length,1));
			myFrame.setSize(defaultDimension,defaultDimension*numbers.length);
		}
		for(int i = 0 ; i < numbers.length ; i++){
			myFrame.getContentPane().add(
					new ComplexNumberPanel(myFrame,numbers[i],75f,editable)
			);
		}
		
		myFrame.setVisible(true);
	}
	public static JPanel display(int defaultDimension,boolean horizontal , boolean editable, ComplexNumber ... numbers){
		return display(100f, defaultDimension,  horizontal ,editable, numbers);
	}
	public static JPanel display(float scale,int defaultDimension,boolean horizontal , boolean editable, ComplexNumber ... numbers){
		JPanel mainPanel = new JPanel();
		if(horizontal){
			mainPanel.setLayout(new GridLayout(1,numbers.length));
			mainPanel.setSize(defaultDimension*numbers.length,defaultDimension);
		}
		else{
			mainPanel.setLayout(new GridLayout(numbers.length,1));
			mainPanel.setPreferredSize(new Dimension(defaultDimension,defaultDimension*numbers.length));
		}
		for(int i = 0 ; i < numbers.length ; i++){
			mainPanel.add(
					new ComplexNumberPanel(mainPanel,numbers[i],scale,editable)
			);
		}
		
		return mainPanel;
	}
	
	public static ComplexNumber parse(String t){
		String [] data = t.split(",");
		return new ComplexNumber((float)Double.parseDouble(data[0]),(float)Double.parseDouble(data[1]));
	}
	public static ComplexNumber [] parseArray(String t){
		String [] data = t.split("\n");
		ComplexNumber [] returnArray = new ComplexNumber[data.length];
		for(int i = 0 ; i < data.length ; i++) returnArray[i] = ComplexNumber.parse(data[i]);
		return returnArray;
	}
}